Skip to content

Conversation

@gn00295120
Copy link
Contributor

@gn00295120 gn00295120 commented Oct 22, 2025

Summary

This PR fixes issue #1443 where passing invalid tool types (e.g., raw functions instead of FunctionTool objects) in the tools list would pass initialization but fail at runtime.

Problem

Currently, when users mistakenly pass raw functions or other invalid types in the tools parameter, the error only appears during runtime:

agent = Agent(
    name="Test",
    tools=[some_function]  # Raw function, not FunctionTool
)

# Agent creation succeeds ✅

result = await Runner.run(agent, "test")
# ❌ Runtime error: AttributeError: 'function' object has no attribute 'name'
#    (in src/agents/run.py line 584)

This is confusing because:

  1. The error happens far from where the mistake was made
  2. The error message doesn't clearly explain what went wrong
  3. Users might not understand they need to use @function_tool decorator

Why AttributeError Occurs at Runtime

The root cause is in src/agents/run.py:584:

current_span.span_data.tools = [t.name for t in all_tools]

This code assumes all items in all_tools have a .name attribute. However:

  • Raw Python functions (type function) do NOT have a .name attribute (they only have __name__)
  • Valid Tool objects (FunctionTool, FileSearchTool, etc.) all have a .name attribute

When a raw function reaches this line, Python raises AttributeError: 'function' object has no attribute 'name'.

The existing validation in Agent.__post_init__ only checks if tools is a list, not the type of each element:

if not isinstance(self.tools, list):
    raise TypeError("Agent tools must be a list, got ...")
# ❌ Does not validate individual tool types

Solution

Add validation in Agent.__post_init__ to check each tool in the list:

agent = Agent(
    name="Test",
    tools=[some_function]
)
# ❌ Immediate error at initialization:
# UserError: tools[0] must be a valid Tool object (FunctionTool, FileSearchTool, ...),
# got function. Did you forget to use @function_tool decorator or pass the function
# itself instead of a tool?

This provides better developer experience by:

  • Early detection: Errors caught at initialization, not runtime
  • Clear error messages: Explicitly states what went wrong
  • Helpful suggestions: Mentions @function_tool decorator when raw functions detected

Changes

src/agents/agent.py:

  • Added UserError import at module level
  • Added validation loop in __post_init__ to check each tool type using get_args(Tool)
  • Uses dynamic type extraction to automatically include all Tool types (FunctionTool, FileSearchTool, WebSearchTool, ComputerTool, HostedMCPTool, LocalShellTool, ImageGenerationTool, CodeInterpreterTool, and Handoff)

tests/test_agent_config.py:

  • Added test_tools_content_validation_issue_1443 with 3 test cases:
    • Case 1: Raw function in tools list
    • Case 2: String in tools list
    • Case 3: Mixed valid and invalid tools (verifies correct index is reported)

Testing

All tests pass:

pytest tests/test_agent_config.py::TestAgentValidation -v
# 6 passed

Note on PR #1927

This PR builds on the learnings from PR #1927. While #1927 attempted to change TypeError to UserError for existing validations, this PR adds new validation that was previously missing, preventing runtime AttributeError by catching invalid tool types early.

Fixes #1443

Copilot AI review requested due to automatic review settings October 22, 2025 15:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes issue #1443 by adding validation to detect invalid tool types during Agent initialization, preventing confusing runtime AttributeErrors. The fix validates that each item in the tools list is an instance of a valid Tool type before the agent is used.

Key changes:

  • Added early validation in Agent.__post_init__ to check tool types and provide clear error messages
  • Enhanced imports to include all valid tool types for validation
  • Added comprehensive test coverage for invalid tool scenarios

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/agents/agent.py Added tool type validation logic in __post_init__ and expanded tool imports for validation
tests/test_agent_config.py Added test cases validating error handling for invalid tool types (raw functions, strings, mixed valid/invalid)

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 261 to 274
# Validate each tool is a valid Tool type
for i, tool in enumerate(self.tools):
if not isinstance(
tool,
(
FunctionTool,
FileSearchTool,
WebSearchTool,
ComputerTool,
LocalShellTool,
ImageGenerationTool,
CodeInterpreterTool,
Handoff,
),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow HostedMCPTool in tools validation

The new __post_init__ check enumerates acceptable tool classes but omits HostedMCPTool, even though Agent.tools is typed as list[Tool] and Tool already includes HostedMCPTool. Any existing agent that supplies a hosted MCP tool (previously valid) will now fail initialization with UserError, breaking integrations that rely on hosted MCP servers. Consider either checking isinstance(tool, Tool) or adding HostedMCPTool to the tuple so valid tools continue to pass.

Useful? React with 👍 / 👎.

…buteError (fixes openai#1443)

This fix addresses issue openai#1443 where passing invalid tool types (e.g., raw
functions instead of FunctionTool objects) in the tools list would pass
initialization but fail at runtime with:

  AttributeError: 'function' object has no attribute 'name'
  (in src/agents/run.py line 584)

Changes:
- Added validation in Agent.__post_init__ to check each tool in the list
- Invalid tools now raise UserError at initialization with helpful message
- Suggests using @function_tool decorator when raw functions are detected

This provides better developer experience by:
1. Catching errors early (at init vs runtime)
2. Providing clear error messages
3. Suggesting the correct fix

Test Coverage:
- Added test_tools_content_validation_issue_1443 with 3 test cases
- Tests raw functions, strings, and mixed valid/invalid tools
- Verifies correct error index is reported
@gn00295120 gn00295120 force-pushed the fix/tool-validation-1443 branch from 969a695 to ad0d90b Compare October 22, 2025 15:20
@gn00295120
Copy link
Contributor Author

Thanks for the review! I've updated the code to use get_args(Tool) to dynamically extract valid tool types from the Tool Union type. This makes the code more maintainable - any future Tool subclasses added to the Tool Union will be automatically validated without code changes.

Changes:

  • Removed explicit import of all concrete tool types
  • Use typing.get_args(Tool) to dynamically get valid types
  • Error message now automatically includes all valid types from the Union

This approach is cleaner and future-proof! ✨

@gn00295120
Copy link
Contributor Author

Thanks for catching that! However, I've already updated the code to use get_args(Tool) which dynamically extracts all types from the Tool Union. This means HostedMCPTool is automatically included:

from typing import get_args
valid_tool_types = get_args(Tool) + (Handoff,)

When I run this, it returns:

FunctionTool, FileSearchTool, WebSearchTool, ComputerTool, 
HostedMCPTool, LocalShellTool, ImageGenerationTool, 
CodeInterpreterTool, Handoff

So existing agents using HostedMCPTool will continue to work! ✅

The benefit of this approach is that any future tool types added to the Tool Union will be automatically validated without code changes.

# Tool is a Union type, so we need to get the valid types from it
from typing import get_args

valid_tool_types = get_args(Tool) + (Handoff,)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe Handoff should not be included in valid_tool_types.

See the related discussion here:
#1897 (comment)


# Validate each tool is a valid Tool type
# Tool is a Union type, so we need to get the valid types from it
from typing import get_args
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this import should be placed at the top of the file with the other imports.

@seratch
Copy link
Member

seratch commented Oct 23, 2025

Thanks for sending this. The latest code already validates if the "tools" is a list object. So, the original issue could be closed now.

@seratch seratch closed this Oct 23, 2025
@gn00295120 gn00295120 deleted the fix/tool-validation-1443 branch October 23, 2025 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UserError not raised when invalid tool type is passed to tools parameter

3 participants